﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TasksUI
{
    public partial class TaskDetails : Form
    {
        public TaskDetails()
        {
            InitializeComponent();
        }

        public TaskDetails(TasksModel.TaskLibrary lib, TasksModel.Task t)
            : this()
        {
            gbxDaily.Top = 104;
            gbxMonthly.Top = 104;
            gbxWeekly.Top = 104;
            gbxYearly.Top = 104;

            _library = lib;
            _task = t;
            _modifiedTask = new TasksModel.Task(t);// deep copy

            Text += _task.LocalCreatedAt.ToString(" HH:mm dd-MM-yyyy");
            // status
            cbStatus.DisplayMember = "Name";
            cbStatus.ValueMember = "ID";
            cbStatus.DataSource = _library.Statuses;
            if (_task.Status != null)
                cbStatus.SelectedValue = _task.Status.ID;
            // non-binded properties
            tbTags.Text = _task.Tags.ToCommaList();
            tbUrl.Text = _task.Url;
            rbHigh.Checked = _task.Priority == TasksModel.PriorityClass.High;
            rbMedium.Checked = _task.Priority == TasksModel.PriorityClass.Medium;
            rbLow.Checked = _task.Priority == TasksModel.PriorityClass.Low;
            // dependencies
            clb.DisplayMember = "Name";
            clb.Items.AddRange(_library.Tasks.AllTasks.OrderBy(delegate(TasksModel.Task ta)
            {
                return ta.Name;
            }).Where(ta => ta.ID != _task.ID).ToArray());
            if (_task.Dependencies != null && _task.Dependencies.Count > 0)
            {
                int archived = 0;
                foreach(TasksModel.Task ta in _task.Dependencies)
                {
                    int i = clb.Items.IndexOf(ta);
                    if (i >= 0)
                        clb.SetItemChecked(i, true);
                    else
                        archived++;// item set but not on current list
                }
                _archivedDependant = archived;
                lCountNum.Text = string.Format("{0} ({1})",
                    clb.CheckedIndices.Count + _archivedDependant, _archivedDependant);
            }
            // flags
            clbFlags.DisplayMember = "Name";
            clbFlags.Items.AddRange(_library.Flags.Sort(delegate(TasksModel.TaskFlag f)
            {
                return f.Name;
            }).ToArray());
            if (_task.Flags != null && _task.Flags.Count > 0)
            {
                foreach (TasksModel.TaskFlag tf in _task.Flags)
                {
                    int i = clbFlags.Items.IndexOf(tf);
                    if (i >= 0)
                        clbFlags.SetItemChecked(i, true);
                }
            }
            // attachments
            lbAtt.DisplayMember = "FileName";
            lbAtt.BeginUpdate();
            foreach (TasksModel.TaskAttachment ta in _modifiedTask.Attachments)
                lbAtt.Items.Add(ta);
            lbAtt.EndUpdate();
            if (lbAtt.Items.Count > 0)
                lbAtt.SelectedIndex = 0;
            if (_modifiedTask.CreatedBy != null)
                lbAuthor.Text = _modifiedTask.CreatedBy.Name;
            lbTimeZone.Text = TimeZoneInfo.FindSystemTimeZoneById(_modifiedTask.TimeZone).DisplayName;

            // RecurrenceDetails
            #region cbRecType
            cbRecType.DisplayMember = "Description";
            cbRecType.ValueMember = "Name";
            TasksModel.TaskStatus ts =new TasksModel.TaskStatus();
            ts.Name = TasksModel.TaskRecurrence.RecurrenceType.Daily.ToString();
            ts.Description = "Daily";
            cbRecType.Items.Add(ts);
            ts = new TasksModel.TaskStatus();
            ts.Name = TasksModel.TaskRecurrence.RecurrenceType.Weekly.ToString();
            ts.Description = "Weekly";
            cbRecType.Items.Add(ts);
            ts = new TasksModel.TaskStatus();
            ts.Name = TasksModel.TaskRecurrence.RecurrenceType.Monthly.ToString();
            ts.Description = "Monthly";
            cbRecType.Items.Add(ts);
            ts = new TasksModel.TaskStatus();
            ts.Name = TasksModel.TaskRecurrence.RecurrenceType.LastDayOfMonth.ToString();
            ts.Description = "Last day of month";
            cbRecType.Items.Add(ts);
            ts = new TasksModel.TaskStatus();
            ts.Name = TasksModel.TaskRecurrence.RecurrenceType.Yearly.ToString();
            ts.Description = "Yearly";
            cbRecType.Items.Add(ts);
            #endregion

            #region cbEvery
            cbEvery.DisplayMember = "Description";
            cbEvery.ValueMember = "Name";
            ts = new TasksModel.TaskStatus();
            ts.Description = "1 day";
            ts.Name = "1";
            cbEvery.Items.Add(ts);
            ts = new TasksModel.TaskStatus();
            ts.Description = "2 days";
            ts.Name = "2";
            cbEvery.Items.Add(ts);
            ts = new TasksModel.TaskStatus();
            ts.Description = "3 days";
            ts.Name = "3";
            cbEvery.Items.Add(ts);
            ts = new TasksModel.TaskStatus();
            ts.Description = "4 days";
            ts.Name = "4";
            cbEvery.Items.Add(ts);
            ts = new TasksModel.TaskStatus();
            ts.Description = "5 days";
            ts.Name = "5";
            cbEvery.Items.Add(ts);
            ts = new TasksModel.TaskStatus();
            ts.Description = "6 days";
            ts.Name = "6";
            cbEvery.Items.Add(ts);
            ts = new TasksModel.TaskStatus();
            ts.Description = "7 days";
            ts.Name = "7";
            cbEvery.Items.Add(ts);
            #endregion

            if (_task.RecurrenceDetails != null)
            {
                lNextOccur.Visible = _task.Reocurring;
                if (_task.RecurrenceDetails.Type != TasksModel.TaskRecurrence.RecurrenceType.None)
                {
                    cbReocurring.Checked = true;
                    SelectValue(cbRecType, _task.RecurrenceDetails.Type.ToString());
                }
                else
                    cbRecType.SelectedIndex = -1;
                if (_task.RecurrenceDetails.EveryDays > 0)
                    SelectValue(cbEvery, _task.RecurrenceDetails.EveryDays.ToString());
                else
                    cbEvery.SelectedIndex = -1;
                dtStart.Checked = true;
                dtStart.Value = _task.RecurrenceDetails.LocalBeginFrom(_task.TimeZone);
                if (_task.RecurrenceDetails.EndAt.HasValue)
                {
                    dtEnd.Checked = true;
                    dtEnd.Value = _task.RecurrenceDetails.LocalEndAt(_task.TimeZone).Value;
                }
                else
                    dtEnd.Checked = false;
                if (_task.RecurrenceDetails.WeeklyDays != null)
                {
                    cbMonday.Checked = Has(_task.RecurrenceDetails.WeeklyDays, DayOfWeek.Monday);
                    cbTuesday.Checked = Has(_task.RecurrenceDetails.WeeklyDays, DayOfWeek.Tuesday);
                    cbWednesday.Checked = Has(_task.RecurrenceDetails.WeeklyDays, DayOfWeek.Wednesday);
                    cbThursday.Checked = Has(_task.RecurrenceDetails.WeeklyDays, DayOfWeek.Thursday);
                    cbFriday.Checked = Has(_task.RecurrenceDetails.WeeklyDays, DayOfWeek.Friday);
                    cbSaturday.Checked = Has(_task.RecurrenceDetails.WeeklyDays, DayOfWeek.Saturday);
                    cbSunday.Checked = Has(_task.RecurrenceDetails.WeeklyDays, DayOfWeek.Sunday);
                }
                if (_task.RecurrenceDetails.DayOfMonth > 0)
                    nudDayOfM.Value = _task.RecurrenceDetails.DayOfMonth;
                if (_task.RecurrenceDetails.DayOfYear > 0)
                    nudDayOfY.Value = _task.RecurrenceDetails.DayOfYear;
                RecalcNextOccur();
            }
            else
                cbReocurring.Checked = false;
            //_task.TimeZone
        }

        private void SelectValue(ComboBox cb, string value)
        {
            foreach (TasksModel.TaskStatus ts in cb.Items)
                if (ts.Name == value)
                {
                    cb.SelectedItem = ts;
                    return;
                }
            System.Diagnostics.Debug.Assert(false);
        }

        private static bool Has(List<DayOfWeek> list, DayOfWeek dayOfWeek)
        {
            return list.Contains(dayOfWeek);
        }

        #region Public

        public static TasksModel.Task AddNewTask(
            Form owner,
            TasksModel.TaskLibrary lib,
            TasksModel.TaskClass tClass)
        {
            TasksModel.Task t = new TasksModel.Task();
            t.Name = string.Empty;
            t.Priority = TasksModel.PriorityClass.Medium;
            t.Progress = 0;
            t.EstimatedEffort = 0;
            t.Class = tClass;
            t.CreatedAt = DateTime.UtcNow;
            t.RichContent = string.Empty;
            TasksModel.TaskAuthor ta = lib.FindAuthorByName(Environment.UserName);
            if (ta == null)
            {
                ta = new TasksModel.TaskAuthor(Environment.UserName);
                lib.Authors.Add(ta);
                ((Main)owner).AsM.AttachExplicit(ta);
            }
            t.CreatedBy = ta;
            t.Status = lib.Statuses.FirstOrDefault(delegate(TasksModel.TaskStatus ts)
            {
                return ts.IsInitialStatus;
            });

            using (TaskDetails f = new TaskDetails(lib, t))
            {
                DialogResult dr = f.ShowDialog(owner);
                if (dr == DialogResult.OK)
                {
                    f.PopulateChanges(owner);
                    return f._task;
                }
            }
            return null;
        }

        public static void EditTask(Form owner,
            TasksModel.TaskLibrary lib, TasksModel.Task task)
        {
            using (TaskDetails f = new TaskDetails(lib, task))
            {
                DialogResult dr = f.ShowDialog(owner);
                if (dr == DialogResult.OK)
                {
                    f.PopulateChanges(owner);
                }
            }
        }

        public static void ViewTask(Form owner,
            TasksModel.TaskLibrary lib, TasksModel.Task task)
        {
            using (TaskDetails f = new TaskDetails(lib, task))
            {
                f.ReadOnly = true;
                f.ShowDialog(owner);
            }
        }

        #endregion

        private void PopulateChanges(Form owner)
        {
            _task.SuspendChangedEvent();
            // simple properties
            _task.DueDate = _modifiedTask.DueDate;
            _task.EstimatedEffort = _modifiedTask.EstimatedEffort;
            _task.Name = _modifiedTask.Name;
            _task.Priority = _modifiedTask.Priority;
            _task.Private = _modifiedTask.Private;
            _task.Reocurring = _modifiedTask.Reocurring;
            _task.Progress = _modifiedTask.Progress;
            _task.RichContent = _modifiedTask.RichContent;
            _task.NoSynch = _modifiedTask.NoSynch;
            _task.TimeZone = _modifiedTask.TimeZone;
            _task.Location = _modifiedTask.Location;
            _task.Status = _modifiedTask.Status;
            _task.AllDay = _modifiedTask.AllDay;
            _task.Url = _modifiedTask.Url;

            // tags
            _task.Tags.Clear();
            string[] tags = tbTags.Text.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string tag in tags)
                _task.Tags.Add(tag.Trim());

            // flags
            _task.Flags.SuspendChangedEvents();
            _task.Flags.Clear();
            foreach (TasksModel.TaskFlag f in clbFlags.CheckedItems)
                _task.Flags.Add(f);// already sorted earlier
            _task.Flags.ResumeChangedEvents();

            // dependencies
            _task.Dependencies.SuspendChangedEvents();
            // remove all but archived
            for (int i = _task.Dependencies.Count - 1; i >= 0; i--)
                if (!_task.Dependencies[i].Archived)
                    _task.Dependencies.RemoveAt(i);
            // add all selected
            foreach (TasksModel.Task t in clb.SelectedItems)
                _task.Dependencies.Insert(0, t);
            _task.Dependencies.ResumeChangedEvents();

            // attachments
            _task.Attachments.SuspendChangedEvents();
            _task.Attachments.Clear();
            foreach (TasksModel.TaskAttachment ta in _modifiedTask.Attachments)
                _task.Attachments.Add(ta);
            _task.Attachments.ResumeChangedEvents();

            // recurrence
            if (!_task.Reocurring)
            {
                if (_task.RecurrenceDetails != null)
                    ((Main)owner).AsM.DetachExplicit(_task.RecurrenceDetails);
                _task.RecurrenceDetails = null;
            }
            else
            {
                if (_task.RecurrenceDetails == null)
                {
                    _task.RecurrenceDetails = new TasksModel.TaskRecurrence();
                    ((Main)owner).AsM.AttachExplicit(_task.RecurrenceDetails);
                }
                _task.RecurrenceDetails.Type = (TasksModel.TaskRecurrence.RecurrenceType)Enum.Parse(
                    typeof(TasksModel.TaskRecurrence.RecurrenceType),
                    ((TasksModel.TaskStatus)cbRecType.SelectedItem).Name);
                _task.RecurrenceDetails.BeginFrom = dtStart.Value.ToUniversalTime();
                if (dtEnd.Checked)
                    _task.RecurrenceDetails.EndAt = dtEnd.Value.ToUniversalTime();
                else
                    _task.RecurrenceDetails.EndAt = null;
                if (_task.RecurrenceDetails.Type == TasksModel.TaskRecurrence.RecurrenceType.Monthly)
                    _task.RecurrenceDetails.DayOfMonth = (int)nudDayOfM.Value;
                else
                    _task.RecurrenceDetails.DayOfMonth = 0;
                if (_task.RecurrenceDetails.Type == TasksModel.TaskRecurrence.RecurrenceType.Yearly)
                    _task.RecurrenceDetails.DayOfYear = (int)nudDayOfY.Value;
                else
                    _task.RecurrenceDetails.DayOfYear = 0;
                if (_task.RecurrenceDetails.Type == TasksModel.TaskRecurrence.RecurrenceType.Daily)
                    _task.RecurrenceDetails.EveryDays = Convert.ToInt32(
                        ((TasksModel.TaskStatus)cbEvery.SelectedItem).Name);
                else
                    _task.RecurrenceDetails.EveryDays = 0;
                if (_task.RecurrenceDetails.Type == TasksModel.TaskRecurrence.RecurrenceType.Weekly)
                {
                    _task.RecurrenceDetails.WeeklyDays = new List<DayOfWeek>(1);
                    if (cbMonday.Checked)
                        _task.RecurrenceDetails.WeeklyDays.Add(DayOfWeek.Monday);
                    if (cbTuesday.Checked)
                        _task.RecurrenceDetails.WeeklyDays.Add(DayOfWeek.Tuesday);
                    if (cbWednesday.Checked)
                        _task.RecurrenceDetails.WeeklyDays.Add(DayOfWeek.Wednesday);
                    if (cbThursday.Checked)
                        _task.RecurrenceDetails.WeeklyDays.Add(DayOfWeek.Thursday);
                    if (cbFriday.Checked)
                        _task.RecurrenceDetails.WeeklyDays.Add(DayOfWeek.Friday);
                    if (cbSaturday.Checked)
                        _task.RecurrenceDetails.WeeklyDays.Add(DayOfWeek.Saturday);
                    if (cbSunday.Checked)
                        _task.RecurrenceDetails.WeeklyDays.Add(DayOfWeek.Sunday);
                } else
                    _task.RecurrenceDetails.WeeklyDays = null;
            }
            _task.ChangedAt = DateTime.UtcNow;
            _task.ResumeChangedEvent();
            _task.ForcePropertyChanged();
        }

        #region Private fields

        private bool ReadOnly
        {
            get { return !tbName.Enabled; }
            set
            {
                bOK.Visible = value;
                bSave.Visible = !value;
                bCancel.Visible = !value;
                tbName.Enabled = !value;
                tbUrl.Enabled = !value;
                tbTags.Enabled = !value;
                cbStatus.Enabled = !value;
                rbHigh.Enabled = !value;
                rbLow.Enabled = !value;
                rbMedium.Enabled = !value;
                rtbNotes.Enabled = !value;
                nudEstim.Enabled = !value;
                nudProgress.Enabled = !value;
                dtpDue.Enabled = !value;
                cbPrivate.Enabled = !value;
                cbSync.Enabled = !value;
                tbLocation.Enabled = !value;
                cbReocurring.Enabled = !value;
                clb.SelectionMode = value ? SelectionMode.None : SelectionMode.One;
                clbFlags.SelectionMode = value ? SelectionMode.None : SelectionMode.One;
                lbAtt.SelectionMode = value ? SelectionMode.None : SelectionMode.One;
                bRemove.Enabled = !value;
                bAttach.Enabled = !value;
                cbAllDay.Enabled = !value;
                gbxDaily.Enabled = !value;
                gbxMonthly.Enabled = !value;
                gbxWeekly.Enabled = !value;
                gbxYearly.Enabled = !value;
                cbRecType.Enabled = !value;
                cbReocurring.Enabled = !value;
                dtEnd.Enabled = !value;
                dtStart.Enabled = !value;
                if (value)
                    this.CancelButton = bOK;
            }
        }

        private int _archivedDependant;

        private TasksModel.Task _task { get; set; }

        private TasksModel.TaskLibrary _library { get; set; }

        private TasksModel.Task _modifiedTask
        {
            get { return taskBindingSource.DataSource as TasksModel.Task; }
            set { taskBindingSource.DataSource = value; }
        }

        #endregion

        #region Radios

        private void rbMedium_CheckedChanged(object sender, EventArgs e)
        {
            if (rbMedium.Checked)
                Check(false, true, false);
        }

        private void rbHigh_CheckedChanged(object sender, EventArgs e)
        {
            if (rbHigh.Checked)
                Check(true, false, false);
        }

        private void rbLow_CheckedChanged(object sender, EventArgs e)
        {
            if (rbLow.Checked)
                Check(false, false, true);
        }

        private void Check(bool a, bool b, bool c)
        {
            if (!a)
                rbHigh.Checked = a;
            else
                _modifiedTask.Priority = TasksModel.PriorityClass.High;
            if (!b)
                rbMedium.Checked = b;
            else
                _modifiedTask.Priority = TasksModel.PriorityClass.Medium;
            if (!c)
                rbLow.Checked = c;
            else
                _modifiedTask.Priority = TasksModel.PriorityClass.Low;
        }

        #endregion

        #region Event handlers

        private void cbStatus_SelectedIndexChanged(object sender, EventArgs e)
        {
            _modifiedTask.Status = cbStatus.SelectedItem as TasksModel.TaskStatus;
        }

        #region Attachments

        private void clb_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            TasksModel.Task t = (TasksModel.Task)clb.Items[e.Index];
            if (t.ID == _task.ID)
            {
                e.NewValue = CheckState.Unchecked;
                MessageBox.Show("Cannot depend in self.", "Error", MessageBoxButtons.OK);
                return;
            }
            if (t.Dependencies != null && t.Dependencies.Contains(_task))
            {
                e.NewValue = CheckState.Unchecked;
                MessageBox.Show("Circular reference found.", "Error", MessageBoxButtons.OK);
                return;
            }
            if (e.NewValue == CheckState.Checked)
                lCountNum.Text = string.Format("{0} ({1})",
                    clb.CheckedIndices.Count + _archivedDependant + 1, _archivedDependant);
            else
                lCountNum.Text = string.Format("{0} ({1})",
                    clb.CheckedIndices.Count + _archivedDependant - 1, _archivedDependant);
        }

        private void bRemove_Click(object sender, EventArgs e)
        {
            TasksModel.TaskAttachment ta = (TasksModel.TaskAttachment)lbAtt.SelectedItem;
            _modifiedTask.Attachments.Remove(ta);
            lbAtt.Items.Remove(ta);
            System.Diagnostics.Debug.Assert(lbAtt.Items.Count == _modifiedTask.Attachments.Count);
            if (lbAtt.Items.Count == 0)
            {
                tbAttDesc.Text = string.Empty;
                lAttNameContent.Text = string.Empty;
                lAttSizeContent.Text = string.Empty;
            }
        }

        private void lbAtt_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lbAtt.SelectedItem == null)
            {
                bRemove.Enabled = false;
                tbAttDesc.Enabled = false;
                tbAttDesc.Text = string.Empty;
                lAttNameContent.Text = string.Empty;
                lAttSizeContent.Text = string.Empty;
                return;
            }
            // show details
            TasksModel.TaskAttachment ta = (TasksModel.TaskAttachment)lbAtt.SelectedItem;
            lAttNameContent.Text = ta.FileName;
            lAttSizeContent.Text = ta.Content == null ? "0" : ta.Content.Length.ToString();
            tbAttDesc.Text = ta.Description;
            tbAttDesc.Enabled = true;
            bRemove.Enabled = true;
        }

        private void tbAttDesc_TextChanged(object sender, EventArgs e)
        {
            if (lbAtt.SelectedItem == null)
                return;
            TasksModel.TaskAttachment ta = (TasksModel.TaskAttachment)lbAtt.SelectedItem;
            ta.Description = tbAttDesc.Text;
        }

        private void bAttach_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog d = new OpenFileDialog())
            {
                d.AddExtension = true;
                d.AutoUpgradeEnabled = true;
                d.CheckFileExists = true;
                d.CheckPathExists = true;
                d.DereferenceLinks = true;
                d.Filter = "All files (*.*)|*.*";
                d.Multiselect = false;
                d.ReadOnlyChecked = true;
                d.RestoreDirectory = true;
                d.ShowReadOnly = false;
                d.Title = "Select file to add as attachment";
                d.InitialDirectory = System.IO.Directory.GetCurrentDirectory();
                if (d.ShowDialog(this) == DialogResult.OK)
                {
                    System.IO.Stream s = d.OpenFile();
                    if (s.Length >= int.MaxValue)
                        throw new InvalidOperationException("File too large to open.");
                    Cursor = Cursors.WaitCursor;
                    Application.DoEvents();
                    try
                    {
                        int read;
                        System.IO.MemoryStream ms = new System.IO.MemoryStream((int)s.Length);
                        byte[] buffer = new byte[8192];
                        do
                        {
                            read = s.Read(buffer, 0, buffer.Length);
                            if (read > 0)
                                ms.Write(buffer, 0, read);
                        } while (read > 0);
                        TasksModel.TaskAttachment ta = new TasksModel.TaskAttachment();
                        ta.Content = ms.ToArray();
                        ms = null;
                        ta.FileName = System.IO.Path.GetFileName(d.FileName);
                        _modifiedTask.Attachments.Add(ta);
                        lbAtt.SelectedIndex = lbAtt.Items.Add(ta);
                    }
                    finally
                    {
                        Cursor = Cursors.Default;
                    }
                }
            }
        }
        
        #endregion

        private void tpMain_Enter(object sender, EventArgs e)
        {
            tbName.Focus();
        }

        private void bSave_Click(object sender, EventArgs e)
        {
            DialogResult = System.Windows.Forms.DialogResult.OK;
        }

        private void tbUrl_DoubleClick(object sender, EventArgs e)
        {
            if (tbUrl.Text.Length < 5)
                return;
            System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(
                tbUrl.Text.Trim());
            psi.UseShellExecute = true;
            System.Diagnostics.Process.Start(psi);
        }

        #endregion

        #region Reocurence

        private void cbRecType_SelectedIndexChanged(object sender, EventArgs e)
        {
            TasksModel.TaskRecurrence.RecurrenceType t = (TasksModel.TaskRecurrence.RecurrenceType)Enum.Parse(
                   typeof(TasksModel.TaskRecurrence.RecurrenceType),
                   ((TasksModel.TaskStatus)cbRecType.SelectedItem).Name);
            gbxMonthly.Visible = t == TasksModel.TaskRecurrence.RecurrenceType.Monthly;
            gbxYearly.Visible = t == TasksModel.TaskRecurrence.RecurrenceType.Yearly;
            gbxWeekly.Visible = t == TasksModel.TaskRecurrence.RecurrenceType.Weekly;
            gbxDaily.Visible = t == TasksModel.TaskRecurrence.RecurrenceType.Daily;
            if (t != TasksModel.TaskRecurrence.RecurrenceType.None)
                RecalcNextOccur();
        }

        private void cbReocurring_CheckedChanged(object sender, EventArgs e)
        {
            gbxRecc.Enabled = cbReocurring.Checked;
            if (cbRecType.SelectedItem == null)
            {
                cbRecType.SelectedIndex = 0;
                if (cbEvery.SelectedIndex < 0)
                    cbEvery.SelectedIndex = 0;
            }
        }

        private void RecalcNextOccur()
        {
            if (!cbReocurring.Checked)
                return;
            TasksModel.TaskRecurrence RecurrenceDetails = new TasksModel.TaskRecurrence();
            RecurrenceDetails.Type = (TasksModel.TaskRecurrence.RecurrenceType)Enum.Parse(
                    typeof(TasksModel.TaskRecurrence.RecurrenceType),
                    ((TasksModel.TaskStatus)cbRecType.SelectedItem).Name);
            RecurrenceDetails.BeginFrom = dtStart.Value.ToUniversalTime();
            if (dtEnd.Checked)
                RecurrenceDetails.EndAt = dtEnd.Value.ToUniversalTime();
            else
                RecurrenceDetails.EndAt = null;
            if (RecurrenceDetails.Type == TasksModel.TaskRecurrence.RecurrenceType.Monthly)
                RecurrenceDetails.DayOfMonth = (int)nudDayOfM.Value;
            else
                RecurrenceDetails.DayOfMonth = 0;
            if (RecurrenceDetails.Type == TasksModel.TaskRecurrence.RecurrenceType.Yearly)
                RecurrenceDetails.DayOfYear = (int)nudDayOfY.Value;
            else
                RecurrenceDetails.DayOfYear = 0;
            if (RecurrenceDetails.Type == TasksModel.TaskRecurrence.RecurrenceType.Daily)
                RecurrenceDetails.EveryDays =
                    cbEvery.SelectedIndex < 0 ? 1 :
                    Convert.ToInt32(((TasksModel.TaskStatus)cbEvery.SelectedItem).Name);
            else
                RecurrenceDetails.EveryDays = 0;
            if (RecurrenceDetails.Type == TasksModel.TaskRecurrence.RecurrenceType.Weekly)
            {
                RecurrenceDetails.WeeklyDays = new List<DayOfWeek>(1);
                if (cbMonday.Checked)
                    RecurrenceDetails.WeeklyDays.Add(DayOfWeek.Monday);
                if (cbTuesday.Checked)
                    RecurrenceDetails.WeeklyDays.Add(DayOfWeek.Tuesday);
                if (cbWednesday.Checked)
                    RecurrenceDetails.WeeklyDays.Add(DayOfWeek.Wednesday);
                if (cbThursday.Checked)
                    RecurrenceDetails.WeeklyDays.Add(DayOfWeek.Thursday);
                if (cbFriday.Checked)
                    RecurrenceDetails.WeeklyDays.Add(DayOfWeek.Friday);
                if (cbSaturday.Checked)
                    RecurrenceDetails.WeeklyDays.Add(DayOfWeek.Saturday);
                if (cbSunday.Checked)
                    RecurrenceDetails.WeeklyDays.Add(DayOfWeek.Sunday);
            }
            else
                RecurrenceDetails.WeeklyDays = null;

            RecurrenceDetails.CalculateNextOccurence(DateTime.UtcNow.Date);
            lbNextOccur.Text = RecurrenceDetails.LocalNextOccurence(_task.TimeZone).ToShortDateString();
            if (cbEvery.SelectedIndex < 0)
                cbEvery.SelectedIndex = 0;
        }

        private void dtStart_ValueChanged(object sender, EventArgs e)
        {
            RecalcNextOccur();
        }

        private void dtEnd_ValueChanged(object sender, EventArgs e)
        {
            RecalcNextOccur();
        }

        private void nudDayOfY_ValueChanged(object sender, EventArgs e)
        {
            RecalcNextOccur();
        }

        private void nudDayOfM_ValueChanged(object sender, EventArgs e)
        {
            RecalcNextOccur();
        }

        private void cbDay_CheckedChanged(object sender, EventArgs e)
        {
            RecalcNextOccur();
        }

        private void cbEvery_SelectedIndexChanged(object sender, EventArgs e)
        {
            RecalcNextOccur();
        }

        #endregion
    }
}